#pragma once
#include "FXValue.h"
#include "DAEMatrix.h"
/**
* This class describes a transformation. The transformation can be applied
* to a vector or can be multiplied with another Transform.
* It is possible to create a complex transform by adding transform objects
* together in a TransformList.
* @author Koen Samyn
*/
class Transform: public FXValue
{
public:
	/**
	* Creates a new Transform object.
	*/
	Transform();
	/**
	*  Destroys the Transform object.
	*/
	virtual ~Transform();
	/**
	* Transforms a DAEFloat3 (homogenous coordinate w will be set to 1)
	* and sets the result of the transform in the vOut parameter.
	* @param vOut points to DAEFloat3 object that will contain the result.
	* @param vToTransform the DAEFloat3 object to transform.
	*/
	void TransformVector(DAEFloat3& vOut, DAEFloat3& vToTransform) const;
	/**
	* Transforms a DAEFloat3 (homogenous coordinate w will be set to 1)
	* and sets the result of the transform in the vOut parameter.
	* @param vOut points to DAEFloat4 object that will contain the result.
	* @param vToTransform the DAEFloat3 object to transform.
	*/
	void TransformVector(DAEFloat4& vOut, DAEFloat3& vToTransform) const;
	/**
	* Transform a DAEFloat3 (homogoneous coordinate w will be set to 1)
	* and sets the result of the transform in the vOut parameter.
	* The translation part of this matrix will not be applied.
	* @param vOut points to the DAEFlaot3 object that will contain the result.
	* @param vToTransform the DAEFloat3 object to transform.
	*/
	void TransformNormal(DAEFloat3& vOut,DAEFloat3& vToTransform) const;
	/**
	* Returns a reference to the internal matrix. It is not legal to change
	* this matrix from the outside. (matrix would be out of sync with the transform
	* parameters).
	* This method will recalculate the transform if one of the parameters
	* was changed.
	* @return a pointer to the compiled matrix.
	*/
	const DAEMatrix& GetCompiledMatrix() const ;
	/**
	* Returns the status of the transform, if the transform
	* has changed, the matrix needs to be recompiled.
	* This behaviour will be overriden by the TransformList class.
	* @return true if the transform has changed , false otherwise.
	*/
	virtual bool IsChanged() const {
		return m_Changed;
	}
	/**
	* Reset the matrix to an identity matrix.
	*/
	void Reset();
	/**
	* Resets the parameters of the transform.
	* Must be implemented by subclass.
	*/
	virtual void ResetTransformParameters()=0;
	/**
	* Recalculate the matrix from the parameters.
	*/
	virtual void RecalculateMatrix() const = 0;

	/**
	* Returns the size of the value in bytes.
	* @return the size in bytes.
	*/
	int GetSizeInBytes() const{
		return 16*sizeof(float);
	}
	/**
	* Returns the pointer to the beginning of the value.
	* @return a void pointer to the beginning of the value.
	*/
	const void* GetValuePointer() const{
		const DAEMatrix& matrix = GetCompiledMatrix();
		return matrix.GetValuePointer();
	}
protected:
	/**
	* Bool that indicates a change for this Transform object.
	*/
	mutable bool m_Changed;
	/**
	* The compiled matrix for this transform.
	*/
	mutable DAEMatrix m_CompiledMatrix;
	/**
	* Sets the changed indicator.
	* @param changed set to true if one of the parameters was changed, false if
	* the compiled matrix is synchronized with the transformation parameters.
	*/
	void SetChanged(bool changed) const {m_Changed=changed;}
};